#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdarg.h>


/* The following are custom additions -forever*/

#if !defined(__STDC_VERSION__)
/* __STDC_VERSION__ is defined in C99 and later */
    int isnan(double number) {
        /* Converts double to a 64-bit integer representation */
        uint64_t bits;
        memcpy(&bits, &number, sizeof(bits));

        /* Get index parts (bits 52 to 62) */
        uint64_t exponent = (bits >> 52) & 0x7FF;

        /* Get mantissa parts (bits 0 to 51) */
        uint64_t mantissa = bits & 0xFFFFFFFFFFFFF;

        /* Check whether the definition conforms to the definition of nan */
        if (exponent == 0x7FF && mantissa != 0) {
            return 1; /* is NaN */
        }
        return 0; /* not NaN */
    }


    int isinf(double number) {
        /* Converts double to a 64-bit integer representation */
        uint64_t bits;
        memcpy(&bits, &number, sizeof(bits));

        /* Get symbol bit (bit 63) */
        uint64_t sign = (bits >> 63) & 0x1;

        /* Get the exponent section (52-62) */
        uint64_t exponent = (bits >> 52) & 0x7FF;

        /* Get mantissa parts (bits 0 to 51) */
        uint64_t mantissa = bits & 0xFFFFFFFFFFFFF;

        /* Check the definition of Infinity: the exponent part is all 1, and the mantissa part is all 0 */
        if (exponent == 0x7FF && mantissa == 0) {
            return sign ? -1 : 1; /* Return -1 for negative infinity and 1 for positive infinity */
        }
        return 0; /* Not infinity */
    }


    /* Under the C89 standard, vsnprintf is undefined and provides a custom implementation */
    /* Custom vsnprintf function */
    /* typedef __gnuc_va_list va_list; -> typedef __builtin_va_list __gnuc_va_list; -> __builtin_va_list  */
    /* int vsnprintf(char *__restrict__ __s, size_t __maxlen, const char *__restrict__ __format, struct __va_list_tag *__arg); */
    int vsnprintf(char *__restrict__ __s, size_t __maxlen, const char *__restrict__ __format, va_list ap) {
        int written = 0;
        const char *p = __format;
        char buffer[33];
        int value;

        while (*p) {
            if (*p == '%' && *(p + 1) != '%') {
                p++;
                switch (*p) {
                    case 'd': /* integer */
                        value = va_arg(ap, int);
                        itoa(value, buffer, 10);
                        size_t len = strlen(buffer);
                        if (written + len < __maxlen) {
                            strcpy(__s + written, buffer);
                        }
                        written += len;
                        break;
                    case 's': /* string */
                        {
                            char *s = va_arg(ap, char *);
                            size_t len = strlen(s);
                            if (written + len < __maxlen) {
                                strcpy(__s + written, s);
                            }
                            written += len;
                        }
                        break;
                    default:
                        break;
                }
            } else {
                if ((size_t)(written + 1) < __maxlen) {
                    __s[written] = *p;
                }
                written++;
            }
            p++;
        }

        if ((size_t)written < __maxlen) {
            __s[written] = '\0';
        } else if (__maxlen > 0) {
            __s[__maxlen - 1] = '\0';
        }

        return written;
    }

    /* The C89 standard, without snprintf, provides a custom implementation */
    /* Custom snprintf implementation */
    int snprintf(char *__restrict__ __s, size_t __maxlen, const char *__restrict__ __format, ...) {
        va_list args;
        va_start(args, __format);
        int result = vsnprintf(__s, __maxlen, __format, args);
        va_end(args);
        return result;
    }
#endif